"""
Python 定义函数使用 def 关键字，一般格式如下：
def 函数名 (参数列表) :
      函数体
     [return]

函数代码块以def关键词开头，后接函数标识符名称和圆括号 ()。
任何传入参数和自变量必须放在圆括号中间，圆括号之间可以用于定义参数。
函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。用三个引号括起来,单引号和双引号都可以。
函数参数后面以冒号结束。
函数体开始缩进。
return [表达式] 结束函数，选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
"""

# 函数的注释
def animal(name: str, age: range(1,120), remark: '这是备注') -> None:
    print(name, age, remark)
    pass
animal(name="猫", age=3, remark="这是一个小猫")
print(animal.__annotations__)

# 定义一个函数，函数名是 hellowrod ，存在2个参数，
def helloword(num1, num2):
    """这是一个函数说明：该函数的作用是将2个数进行求和"""
    print(num1 + num2)
    return num1 + num2
# 调用函数
helloword(1, num2=10)

# 定义一个函数，存在一个*号的可变参数，可变参数以元组的形式传入
def hello(num1, num2, *nums, remark):
    print("存在一个*的可变参数", num1, num2, type(nums), nums, remark)
    return len(nums)
hello(1, 2, 3,4,5,6, remark="如果形参中出现了不定长参数，那么在调用函数的时候，先通过位置进行必须参数的匹配，然后不定长参数后面的参数必须通过关键字参数匹配，如果不定长的参数后面还有参数,必须通过关键字参数传参")


# 定义一个函数，存在2个**号的可变参数，参数会以字典的形式传入
def word(num1, **nums):
    print("存在2个**的可变参数",num1, type(nums), nums)
    return nums
word(1, key1= "aa", key2="bb", key3=456)


# 带默认值的参数
def add(num1, num2 = 10):
    print("带默认值的参数", num1 + num2)
add(1)

# 强制使用位置参数或关键字参数 / 前的参数必须使用位置传参，* 后的参数必须用关键字传参。
def f(a, b, /, c, d, *, e, f):
    print("/ 前的参数必须使用位置传参，* 后的参数必须用关键字传参",a, b, c, d, e, f)
f(1, 2, 3, d=4, e=5, f=6)

# 防止函数修改列表  有时要函数对列表进行处理，又不希望函数修改原列表，可以使用 copy.deepcopy()
import copy
def multiply2(var1):
    var1[3].append(400)
    print("函数内处理后：", var1)


# 变量的作用域
"""
Python中，程序的变量并不是在哪个位置都可以访问的，访问权限决定于这个变量是在哪里赋值的。变量的作用域决定了哪一部分程序可以访问哪个变量，Python的作用域一共有4种，分别是：
    （Local） 局部作用域
    （Enclosing）嵌套作用域 闭包函数外的函数中
    （Global） 全局作用域
    （Built-in） 内建作用域
以 L -> E -> G -> B 的规则查找，即：在局部找不到，便会去局部外的局部找（例如闭包），再找不到就会去全局找，再者去内建中找。以下案例演示各种作用域类型。
"""
'''
    该案例演示了变量的作用域
'''
print("*"*20)
print("变量的作用域")
a = int(2.9)  # 内建作用域 (Python本身提供的,在所有位置都可以访问)
b = 0  # 全局作用域
def outer():
    c = 1  # 嵌套作用域
    def inner():
        d = 2  #局部作用域
        print(d,c,b,a)
    return inner
in_func=outer()
in_func()
print("*"*20)

# 全局变量和局部变量（略）

# list的深拷贝
list1 = [1, 2, 3, [100, 200, 300]]
print("函数外处理前：", list1)
multiply2(copy.deepcopy(list1))
print("函数外处理后：", list1)
